package com.cyurs.netty.nio.group;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * 服务端
 * @Author: Cyrus
 * @CreateDate: 2020/11/17
 */
public class GroupChatServer {
    private final int port = 6666; //端口号
    private ServerSocketChannel ListenSocket;
    private Selector selector;

    public GroupChatServer() {
        try {
            ListenSocket = ServerSocketChannel.open();
            selector = Selector.open();
            ListenSocket.socket().bind(new InetSocketAddress(port));
            ListenSocket.configureBlocking(false);
            ListenSocket.register(selector, SelectionKey.OP_ACCEPT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 监听客户端
     */
    public void listen() {
        try {
            while (true) {
                int count = selector.select(); //监听客户端行为
                if (count > 0) { //若存在行为
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); //遍历
                    if (iterator.hasNext()) {
                        SelectionKey key = iterator.next();//获得当前客户端通道
                        if (key.isAcceptable()) {//若为连接操作
                            SocketChannel socketChannel = ListenSocket.accept(); //向客户端创建一个socketChannel通道
                            socketChannel.configureBlocking(false); //关闭阻塞
                            socketChannel.register(selector, SelectionKey.OP_READ);//socketChannel向Selector进行注册
                            System.out.println(socketChannel.getRemoteAddress() + " 连接了....");
                        }
                        if (key.isReadable()) {//若为读取操作
                            readData(key);
                        }
                    } else {

                    }
                    iterator.remove(); //防止重复执行
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }

    /**
     * 读取客户端消息
     */
    public void readData(SelectionKey key) {
        SocketChannel channel = null;
        try {
            channel = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int count = channel.read(buffer);
            if (count > 0) {
                String msg = new String(buffer.array());
                System.out.println("from 客户端："+msg);
                //向其他客户端转发
                sendInfoToOtherClient(msg, channel);
            }

        } catch (IOException e) {
            try {
                System.out.println(channel.getRemoteAddress()+" 离线了...");
                key.cancel(); //取消注册
                channel.close(); //关闭通道

            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

    public void sendInfoToOtherClient(String msg, SocketChannel self) throws IOException {
        System.out.println("服务器转发消息中....");
        for (SelectionKey key : selector.keys()) { //遍历所有SelectionKey
            Channel targetChannel = key.channel(); //通过key反向获取通道
            if (targetChannel instanceof SocketChannel && targetChannel != self) {  //准发给其他通道
                SocketChannel dest = (SocketChannel) targetChannel;
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                dest.write(buffer);
            }
        }
    }

    public static void main(String[] args) {
        GroupChatServer groupChatServer = new GroupChatServer();

        groupChatServer.listen();
    }
}
